package com.cn.sl.server.common.dao

import com.cn.sl.server.common.model.BaseEntity
import com.querydsl.core.BooleanBuilder
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.core.types.dsl.StringPath
import org.springframework.data.domain.Page
import org.springframework.data.domain.Sort

/**
 * @author 阮雪峰
 */
interface BaseDao<T : BaseEntity, R> {
    fun getRepository(): R

    /**
     * 保存
     */
    fun save(entity: T)

    /**
     * 保存全部
     */
    fun saveAll(entities: Collection<T>)

    /**
     * 删除
     */
    fun deleteById(id: Long)

    fun deleteAllById(ids: List<Long>)

    /**
     * 删除
     */
    fun delete(entity: T)

    fun deleteAll(entities: Collection<T>)
    fun deleteAll()

    /**
     * 查询所有
     */
    fun findAll(): List<T>

    /**
     * 分页查询
     */
    fun findAll(act: () -> PageQueryAct): Page<T>

    fun findAll(booleanBuilder: BooleanBuilder): List<T>

    fun findAll(booleanBuilder: BooleanBuilder, sort: Sort): List<T>
    fun findAll(sort: Sort): List<T>

    /**
     * 根据id查询
     */
    fun findById(id: Long): T

    /**
     * 根据id查询，不存在则返回null
     */
    fun findByIdOrNull(id: Long): T?

    fun findAllById(ids: Collection<Long>): List<T>

    fun flush()

    fun <T> strRegexp(list: List<T>, fieldPath: StringPath?, booleanBuilder: BooleanBuilder) {
        val template =
            Expressions.booleanTemplate(
                "regexp({0},{1})",
                fieldPath,
                list.joinToString("|") { obj: T -> obj.toString() }
            )
        booleanBuilder.and(template.eq(true))
    }

    fun fulltextSearch(content: String, fieldPath: StringPath?, booleanBuilder: BooleanBuilder) {
        val template =
            Expressions.booleanTemplate(
                "fulltext_search({0},{1})",
                fieldPath,
                content
            )
        booleanBuilder.and(template.eq(true))
    }

    data class PageQueryAct(
        val booleanBuilder: BooleanBuilder,
        val page: Int,
        val pageSize: Int,
        val sort: Sort
    )
}